package com.biz.handler;

import com.alibaba.fastjson.*;
import com.biz.annotation.*;
import com.biz.entity.*;
import lombok.extern.slf4j.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.transaction.support.*;
import org.springframework.util.*;

import javax.annotation.*;
import java.util.*;
import java.util.concurrent.atomic.*;

/**
 * @Description
 *  抽象归档接口
 * @Author liuxi
 * @Date 2024/5/16
 **/
@Slf4j
public abstract class AbstractBackUpDataHandler<T, V extends BackUpDataRule> implements BackUpDataHandler{

    /**
     * 最大循环次数
     */
    @Value("${back-up.data.max-loop-count:10}")
    private Integer maxLoopCount;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Override
    public String getScence() {
        Class<? extends AbstractBackUpDataHandler> clazz = getClass();
        BackUpData annotation = clazz.getAnnotation(BackUpData.class);
        if (Objects.isNull(annotation)) {
            return "default";
        }
        return annotation.value();
    }

    @Override
    public void backUpData() {
        log.info("AbstractBackUpDataHandler.backUpData.start.scene:{}!", getScence());
        V rule = getRule();
        Integer loopCount = 0;
        log.info("AbstractBackUpDataHandler.backUpData.getRule.scene:{},rule:{}",
                getScence(), JSON.toJSONString(rule));
        while (!needStop()) {
            log.info("AbstractBackUpDataHandler.backUpData.stopFlag.scene:{},stopFlag:{}", getScence(), needStop());
            List<T> dataList = queryData(rule);
            if (CollectionUtils.isEmpty(dataList)) {
                log.info("AbstractBackUpDataHandler.backUpData.queryIsEmpty.scene:{}", getScence());
                if (loopCount >= maxLoopCount) {
                    log.info("AbstractBackUpDataHandler.backUpData.arriveMaxCount.scene:{}", getScence());
                    break;
                }
                rule = changeOffSet(rule);
                loopCount++;
                continue;
            }
            loopCount = 0;
            log.info("AbstractBackUpDataHandler.backUpData.querySize.scene:{},size:{}", getScence(), dataList.size());
            AtomicReference<Boolean> transactionSuccessFlag = new AtomicReference<>(true);
            // 手动提交事务
            transactionTemplate.execute((transactionStatus) -> {
                try {
                    insertData(dataList);
                    deleteData(dataList);
                } catch (Exception e) {
                    log.error("AbstractBackUpDataHandler.backUpData.transferData.fail.scene:{},error:{}",
                            getScence(), e.getMessage(), e);
                    transactionSuccessFlag.set(false);
                    transactionStatus.setRollbackOnly();
                }
                return null;
            });
            if (!transactionSuccessFlag.get()) {
                log.info("AbstractBackUpDataHandler.backUpData.transactionFail.scene:{}", getScence());
                break;
            }
            rule = changeOffSet(rule);
        }
    }

    /**
     * 获取归档规则
     */
    public abstract V getRule();

    /**
     * 是否终止归档
     */
    public abstract Boolean needStop();

    /**
     * 查询数据
     */
    public abstract List<T> queryData(V rule);

    /**
     * 归档偏移量变更
     */
    public abstract V changeOffSet(V rule);

    /**
     * 归档表插入数据
     */
    public abstract void insertData(List<T> dataList);

    /**
     * 删除原表归档数据
     */
    public abstract void deleteData(List<T> dataList);
}
